#include <string>
#include <ostream>
const std::string SEP = "-";

enum class Genre
{
    fiction = 0,
    nonfinction,
    periodical,
    biography,
    children
};

class Book
{
private:
    bool Is_valid_ISBN();
    bool Is_alpha_string(const std::string &string);
    bool Is_digit_string(const std::string &string);
    friend std::ostream &operator<<(std::ostream &out, const Book &book);
    std::string General_To_String(Genre &version)
    {
        switch (version)
        {
        case Genre::fiction:
            return "小说";
        case Genre::nonfinction:
            return "非小说类文学作品";
        case Genre::periodical:
            return "期刊";
        case Genre::biography:
            return "传记";
        case Genre::children:
            return "儿童读物";
        default:
            return "Unknown";
        }
    }

public:
    Book()
    {
    }
    Book(std::string isbn, std::string book_name, std::string author, Genre type);
    class Invalid_ISBN
    {
    };
    bool operator==(const Book &book)
    {
        return _ISBN == book._ISBN;
    }
    bool operator!=(const Book &book)
    {
        return !(operator==(book));
    }
    std::string GetName()
    {
        return _Book_Name;
    }
    Book &operator=(const Book &book)
    {
        _ISBN = book._ISBN;
        _Book_Name = book._Book_Name;
        _Author = book._Author;
        return *this;
    }

private:
    std::string _ISBN;
    std::string _Book_Name;
    std::string _Author;
    bool _is_borrow = false;
    std::string _type;
};

bool Book::Is_valid_ISBN()
{
    size_t start = 0;
    for (int i = 0; i < 3; i++)
    {
        auto pos = _ISBN.find(SEP);
        std::string sep = _ISBN.substr(start, pos);
        if (!Is_digit_string(sep))
        {
            return false;
        }
        start += (pos + SEP.size());
    }
    std::string final = _ISBN.substr(start, _ISBN.size());
    if ((!Is_alpha_string(final)) && (!Is_digit_string(final)))
    {
        return false;
    }
    return true;
}

bool Book::Is_alpha_string(const std::string &str)
{
    if (str.empty())
        return false; // 空字符串不算

    for (char c : str)
    {
        if (!std::isalpha(static_cast<unsigned char>(c)))
        {
            return false;
        }
    }
    return true;
}

bool Book::Is_digit_string(const std::string &str)
{
    if (str.empty())
        return false; // 空字符串不算

    for (char c : str)
    {
        if (!std::isdigit(static_cast<unsigned char>(c)))
        {
            return false;
        }
    }
    return true;
}

Book::Book(std::string isbn, std::string book_name, std::string author, Genre type) : _ISBN(isbn), _Book_Name(book_name), _Author(author)
{
    if (!Is_valid_ISBN())
    {
        throw Invalid_ISBN{};
    }
    _type = General_To_String(type);
}

std::ostream &operator<<(std::ostream &out, const Book &book)
{
    out << "书名：" << book._Book_Name << " 作者：" << book._Author << " ISNB：" << book._ISBN << " 类型：" << book._type << '\n';
    return out;
}